#Written by MMCOWBOY

import pygame
import math
import effect, collidet
#import flame

def get_laser_gun(gun_level, object):
    if (gun_level == 1):
        return laser_gun_level_1(object)
    elif (gun_level == 2):
        return laser_gun_level_2(object)
    elif (gun_level == 3):
        return laser_gun_level_3(object)
    elif (gun_level == 4):
        return laser_gun_level_4(object)
    else:
        return None
    
def get_bomb(bomb_type, object):
    if (bomb_type == 1):
        return bomb_1(object)

class gun_fire(pygame.sprite.Sprite):

    def __init__(self, off_set_x, off_set_y, belong_to):
        super(gun_fire, self).__init__(self.containers)
        self.belong_to = belong_to
        self.off_set_x = off_set_x
        self.off_set_y = off_set_y
        self.image = pygame.image.load("data/images/gunfire.png")
        self.rect = self.image.get_rect(center = (self.off_set_x + self.belong_to.rect.center[0], self.off_set_y + self.belong_to.rect.center[1]))
        self.live_time = 1

    def draw(self, screen):
        screen.blit(self.image, self.rect)

    def update(self):
        if self.live_time:
            self.live_time -= 1
            self.rect.center = (self.off_set_x + self.belong_to.rect.center[0], self.off_set_y + self.belong_to.rect.center[1])
        else:
            self.kill()

class shot_gun(object):
    def __init__(self, belong_to):
        self.belong_to = belong_to
        
    def fire(self):
        pass

class laser_gun_level_1(shot_gun):
    
    def __init__(self, belong_to):
        super(laser_gun_level_1, self).__init__(belong_to)
        self.belong_to = belong_to
        self.shot_sound = pygame.mixer.Sound("data/sounds/w_1_player.WAV")
        self.shot_sound.set_volume(0.25)

    def fire(self):
        self.shot_sound.play()  
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx - 10,self.belong_to.rect.centery - 35),\
                        self.belong_to, shot_obj.LASER_YELLOW)
        gun_fire(-10, -15, self.belong_to)
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx + 10,self.belong_to.rect.centery - 35),\
                        self.belong_to, shot_obj.LASER_YELLOW)
        gun_fire(10, -15, self.belong_to)
        
class laser_gun_level_2(shot_gun):
    
    def __init__(self, belong_to):
        super(laser_gun_level_2, self).__init__(belong_to)
        self.belong_to = belong_to
        self.shot_sound = pygame.mixer.Sound("data/sounds/w_2_player.WAV")
        self.shot_sound.set_volume(0.25)

    def fire(self):
        self.shot_sound.play()  
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx - 10,self.belong_to.rect.centery - 35),\
                        self.belong_to, shot_obj.LASER_BLUE)
        gun_fire(-10, -15, self.belong_to)
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx + 10,self.belong_to.rect.centery - 35),\
                        self.belong_to, shot_obj.LASER_BLUE)
        gun_fire(10, -15, self.belong_to)


class laser_gun_level_3(shot_gun):
        
    def __init__(self, belong_to):
        super(laser_gun_level_3, self).__init__(belong_to)
        self.belong_to = belong_to
        self.shot_sound = pygame.mixer.Sound("data/sounds/w_3_player.WAV")
        self.shot_sound.set_volume(0.25)
    
    def fire(self):
        self.shot_sound.play()  
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx - 10,self.belong_to.rect.centery - 35),\
                        self.belong_to, shot_obj.LASER_BLUE)
        gun_fire(-10, -15, self.belong_to)
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx + 10,self.belong_to.rect.centery - 35),\
                        self.belong_to, shot_obj.LASER_BLUE)
        gun_fire(10, -15, self.belong_to)
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx - 3,self.belong_to.rect.centery - 38),\
                        self.belong_to, shot_obj.LASER_YELLOW)
        gun_fire(-3, -17, self.belong_to)
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx + 3,self.belong_to.rect.centery - 38),\
                        self.belong_to, shot_obj.LASER_YELLOW)
        gun_fire(3, -17, self.belong_to)
        
class laser_gun_level_4(shot_gun):
    
    def __init__(self, belong_to):
        super(laser_gun_level_4, self).__init__(belong_to)
        self.belong_to = belong_to
        self.shot_sound = pygame.mixer.Sound("data/sounds/w_4_player.WAV")
        self.shot_sound.set_volume(0.25)
        
    def fire(self):
        self.shot_sound.play()  
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx - 10,self.belong_to.rect.centery - 35),\
                        self.belong_to, shot_obj.LASER_BLUE)
        gun_fire(-10, -15, self.belong_to)
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx + 10,self.belong_to.rect.centery - 35),\
                        self.belong_to, shot_obj.LASER_BLUE)
        gun_fire(10, -15, self.belong_to)
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx - 3,self.belong_to.rect.centery - 38),\
                        self.belong_to, shot_obj.LASER_BLUE)
        gun_fire(-3, -17, self.belong_to)
        shot_obj(self.belong_to.screen_size, 0, -15,\
                        (self.belong_to.rect.centerx + 3,self.belong_to.rect.centery - 38),\
                        self.belong_to, shot_obj.LASER_BLUE)
        gun_fire(3, -17, self.belong_to)
    
    

class missile_obj(pygame.sprite.Sprite):
    
    angle_turn_limit = 5
    
    def __init__(self, screen_size, position, belong_to = None):
        super(missile_obj, self).__init__(self.containers)
        self.screen_width = screen_size[0]
        self.screen_height = screen_size[1]
        self.original_image = pygame.image.load("data/images/missile.png")
        self.image = self.original_image
        self.rect = self.image.get_rect(center = position)
        self.attack_area = pygame.Rect(0, 0, 600, 600)
        self.power = 5
        self.belong_to = belong_to
        self.attack_list = self.belong_to.attack_list
        self.target = None
        self.angle = 0
        self.speed = -4
        self.speed_x = 0
        self.speed_y = self.speed
        self.flame_off_set_x = 0
        self.flame_off_set_y = -self.image.get_height() / 2.0
        self.explos_sound = pygame.mixer.Sound("data/sounds/missile_explos.wav")
        self.explos_sound.set_volume(0.25)
        
        self.straight_step = 10
        
    def move(self):
            
        if self.target is None:
            self.detect_lock()
            
        if self.straight_step :
            self.straight_step -= 1
        else:
            if self.target:
                if self.target.is_alived():
                        
#                    print "-----------------------------------------------------"
                    t_speed_x, t_speed_y = self.get_shot_speed(self.speed)
                    t_angle = -collidet.angle_to_degree(collidet.get_angle(t_speed_x, t_speed_y))

                    while self.angle < 0 :
                        self.angle += 360.0
                    while self.angle >= 360.0 :
                        self.angle -= 360.0
                        
                    while t_angle < 0 :
                        t_angle += 360.0
                    while t_angle >= 360.0 :
                        t_angle -= 360.0
    
                    td_angle = t_angle - self.angle
                    d_angle = math.fabs(td_angle)

                    while td_angle < 0:
                        td_angle += 360.0
                    while td_angle >= 360.0:
                        td_angle -= 360.0
                        
                    if d_angle > self.angle_turn_limit :
#                        print "A"
                        if td_angle >= 0 and td_angle < 180.0:
#                            print "Case1:"
                            self.angle += self.angle_turn_limit
                            td_angle = -self.angle_turn_limit
                        else:
#                            print "Case2:"
                            self.angle -= self.angle_turn_limit
                            td_angle = +self.angle_turn_limit
                        td_angle = collidet.degree_to_angle(td_angle)
                        self.speed_x, self.speed_y = collidet.trans_dx_dy_angle(self.speed_x, self.speed_y, td_angle)
                        self.flame_off_set_x, self.flame_off_set_y = collidet.get_offsets(self.original_image.get_height() / 2.0, self.angle +180.0)
                        self.flame_off_set_y = -self.flame_off_set_y
                        #-------------------------------------------------------------
                            
                    else:
#                        print "B"
                        self.angle = t_angle
                        self.speed_x, self.speed_y = self.get_shot_speed(self.speed)
                        self.flame_off_set_x, self.flame_off_set_y = self.get_shot_speed(self.original_image.get_height() / 2.0)
                            
#                    print "-----------------------------------------------------"
                else:
                    self.target = None
            
#        self.angle = -collidet.angle_to_degree(collidet.get_angle(self.speed_x, self.speed_y))
            
#        print "speed_x: ",self.speed_x," speed_y: ",self.speed_y
        self.rect = self.rect.move(self.speed_x, self.speed_y)
            
        if (self.rect.right <= 0):
            self.kill()
            return
        if (self.rect.left > self.screen_width):
            self.kill()
            return
        if (self.rect.top > self.screen_height):
            self.kill()
            return
        if (self.rect.bottom <= 0):
            self.kill()
            return
            
            
        effect.flame_spot((self.rect.centerx - self.flame_off_set_x, self.rect.centery - self.flame_off_set_y),\
            -self.speed_x, -self.speed_y, 5, 30)
    
                    
            
    def detect_lock(self):
        mini_dis = -1
        for aobj in self.attack_list:
            dis = collidet.get_distance(self, aobj)
            if (mini_dis == -1 or mini_dis > dis):
                mini_dis = dis
                self.target = aobj

    def get_shot_speed(self, speed):
        if (self.target is None):
            return [0,-speed]
        dx = self.rect.centerx - self.target.rect.centerx
        dy = self.rect.centery - self.target.rect.centery
        if (dx != 0):
            l = float(dy) / dx
            speed_x = math.sqrt((float(speed ** 2) / float(1 + l ** 2)))
            speed_y = abs(l) * speed_x
            if (dx > 0):
                speed_x = -speed_x
            if (dy > 0):
                speed_y = -speed_y
        else:
            speed_x = 0
            if (dy > 0):
                speed_y = -speed
            else:
                speed_y = speed
        return [speed_x,speed_y]

    def rotate(self):       
        center = self.rect.center
        self.image = pygame.transform.rotozoom(self.original_image, self.angle, 1.0)
        self.rect = self.image.get_rect()
        self.rect.center = center
        
    def draw(self, screen):
        screen.blit(self.image, self.rect)
        
    def update(self):
#        print "targe:", self.target
        self.move()
        if (self.angle):
            self.rotate()   
            
    def killed(self):
        self.explos_sound.play()
        effect.spark_obj(self.rect.center, 'Line')
        self.kill()

class shot_obj(pygame.sprite.Sprite):

    LASER_YELLOW = 1
    LASER_BLUE = 2
    LASER_RED = 3

    def __init__(self, screen_size, xspeed, yspeed, position, belong_to = None, laser_type = 1 , angle = 0):

        super(shot_obj, self).__init__(self.containers)
        self.screen_width = screen_size[0]
        self.screen_height = screen_size[1]
        self.xspeed = xspeed
        self.yspeed = yspeed
        self.angle = angle
        self.belong_to = belong_to
        self.target = None
        self.explos_sound = pygame.mixer.Sound("data/sounds/shot_explos.wav")
        self.explos_sound.set_volume(0.15)

        if (laser_type == self.LASER_YELLOW):
            self.image = pygame.image.load("data/images/laser.png")
            self.rect = self.image.get_rect(center = position)
            self.x, self.y = self.rect.center
            self.power = 1

        elif (laser_type == self.LASER_BLUE):
            self.image = pygame.image.load("data/images/laser1.png")
            self.rect = self.image.get_rect(center = position)
            self.x, self.y = self.rect.center
            self.power = 2
        elif (laser_type == self.LASER_RED):
            self.image = pygame.image.load("data/images/laser2.png")
            self.rect = self.image.get_rect(center = position)
            self.x, self.y = self.rect.center
            self.power = 5

        self.rotate()

    def draw(self, screen):
        screen.blit(self.image, self.rect)

    def update(self):
        self.rect.center = self.x, self.y
        self.x += self.xspeed
        self.y += self.yspeed

        if (self.rect.top >= self.screen_height):
            self.kill()
        if (self.rect.bottom <= 0):
            self.kill()
        if (self.rect.right <= 0):
            self.kill()
        if (self.rect.left >= self.screen_width):
            self.kill()
    
    def killed(self):
        self.explos_sound.play()
        effect.spark_obj(self.rect.center, 'Spot', 10, 3)
        self.kill()
    

    def rotate(self):

        center = self.rect.center
        self.image = pygame.transform.rotozoom(self.image, self.angle, 1.0)
        self.rect = self.image.get_rect()
        self.rect.center = center
        
class enemy_shot_obj(pygame.sprite.Sprite):

    GREEN_BALL = 1
    RED_BALL = 2
    

    def __init__(self, screen_size, xspeed, yspeed, position, belong_to = None, laser_type = 1, target = None, angle = 0):

        super(enemy_shot_obj, self).__init__(self.containers)
        self.screen_width = screen_size[0]
        self.screen_height = screen_size[1]
        self.xspeed = xspeed
        self.yspeed = yspeed
        self.angle = angle
        self.belong_to = belong_to
        self.target = target
        self.explos_sound = pygame.mixer.Sound("data/sounds/shot_explos.wav")
        self.explos_sound.set_volume(0.25)
        

        if (laser_type == self.GREEN_BALL):
            self.image = pygame.image.load("data/images/efire1.png")
            self.rect = self.image.get_rect(center = position)
            self.x, self.y = self.rect.center
            self.power = 1

        elif (laser_type == self.RED_BALL):
            self.image = pygame.image.load("data/images/efire2.png")
            self.rect = self.image.get_rect(center = position)
            self.x, self.y = self.rect.center
            self.power = 10

        else:
            pass

#        self.rotate()

    def draw(self, screen):
        screen.blit(self.image, self.rect)

    def update(self):
        self.rect.center = self.x, self.y
        self.x += self.xspeed
        self.y += self.yspeed

        if (self.rect.top >= self.screen_height):
            self.kill()
        if (self.rect.bottom <= 0):
            self.kill()
        if (self.rect.right <= 0):
            self.kill()
        if (self.rect.left >= self.screen_width):
            self.kill()
            
    def killed(self):
        self.explos_sound.play()
        effect.spark_obj(self.rect.center, 'Spot', 10, 3)
        self.kill()
    
    def rotate(self):

        center = self.rect.center
        self.image = pygame.transform.rotozoom(self.image, self.angle, 1.0)
        self.rect = self.image.get_rect()
        self.rect.center = center

class bomb_obj(pygame.sprite.Sprite):
    def __init__(self,belong_to):
        super(bomb_obj, self).__init__(self.containers)
        self.screen_width = belong_to.screen_size[0]
        self.screen_height = belong_to.screen_size[1]
        self.belong_to = belong_to
#        self.target = target
        self.move_step = 0
        self.kill_R = 0
        self.bomb_last_time = 0
        self.isbombed = False
        self.bomb_sound = None

    def draw(self, screen):
        screen.blit(self.image, self.rect)

    def bomb(self):
        pass

    def bombed(self):
        return self.isbombed

    def update(self):
        if (self.move_step):
            self.move_step -= 1
            self.rect = self.rect.move(0, -self.speed)
        else:
            self.bomb()

        if (self.isbombed):
            if (self.bomb_last_time):
                self.bomb_last_time -= 1
            else:
                self.kill()

class bomb_1(bomb_obj):
    
    def __init__(self, belong_to):
        super(bomb_1, self).__init__(belong_to)
        self.image = pygame.image.load("data/images/bomb1.png")
        self.rect = self.image.get_rect(center = belong_to.rect.center)
        self.x, self.y = self.rect.center
        self.kill_R = 150
        self.move_step = 3
        self.bomb_last_time = 3
        self.speed = 15
        self.power = 30
        self.bomb_sound = pygame.mixer.Sound("data/sounds/y_bomb_player.wav")
        
    def bomb(self):
        if (self.isbombed):
            return
            
        self.bomb_sound.play()
            
        effect.shock_wave(self.rect.center, 'Spot', 10)
        effect.shock_wave(self.rect.center, 'Spot', 5)
    
        self.image = pygame.Surface((self.kill_R * 2, self.kill_R * 2))
        pygame.draw.ellipse(self.image, (255 , 255, 0), [0,0,self.kill_R * 2,self.kill_R * 2])
        pygame.draw.ellipse(self.image, (0, 0, 0), [1,1,self.kill_R * 2 - 2,self.kill_R * 2 - 2])
        self.image.set_colorkey((0,0,0), pygame.RLEACCEL)
        self.image.convert()
        self.rect = self.image.get_rect(center = self.rect.center)
            
        #-----------------Bomb flames!!!-------------------------
            
    #        flame.explosion(self.rect.center, 60)
        self.isbombed = True
    